package com.kent.hellokotlin.aStart

import com.google.gson.Gson
import com.google.gson.JsonElement
import java.io.File
import java.math.BigDecimal
import java.nio.file.Files
import java.nio.file.Paths

fun main() {
    //val customer = Customer("David", "David@qq.com")
    //fooExpend()
    ifNotNull()
}

//创建 DTOs（POJOs/POCOs）
data class Customer(val name: String, val email: String)

fun customerFoo() {
    val customer = Customer("Kent", "email")
    customer.name
    customer.email
    customer.hashCode()
    customer.toString()
    customer.copy()
    customer.component1()
    customer.component2()
}

//函数的默认参数
fun foo(a: Int = 0, b: String = "") {}

//过滤List
fun fooList() {
    val numList = listOf(-1, 0, 1, 2, 3)
    var positives = numList.filter { x -> x > 0 }
    positives = numList.filter { it > 0 }
}

//检测元素是否存在于集合中
fun fooList1() {
    val emailList = listOf("1.qq.com", "2.qq.com", "3.qq.com", "4.qq.com", "5.qq.com")
    if ("1.qq.com" in emailList) {

    }
    if ("6.qq.com" !in emailList) {

    }
}

//字符串内插
fun fooStr() {
    val name = "Kent"
    println("Name is $name")
}

//类型判断
/*
when (x) {
    is Foo //-> ……
    is Bar //-> ……
    else   //-> ……
}
*/

//遍历 map/pair型list
fun fooMap() {
    val map: Map<String, Int> = mapOf("a" to 1, "b" to 2, "c" to 3)
    for ((k, v) in map) {
        println("$k --> $v")
    }
}

//只读 list
val list = listOf("a", "b", "c")

//只读 map
val map = mapOf("a" to 1, "b" to 2, "c" to 3)

//访问 map
fun fooMap1() {
    val map = mutableMapOf("a" to 1, "b" to 2, "c" to 3)
    println(map["a"])
    map["a"] = 6
}

//延迟属性
val p: String by lazy { "p" }

//扩展函数
fun String.spaceToCamelCase(): String {
    var lastIsSpace = false
    val resultBuilder: StringBuilder = java.lang.StringBuilder()
    for (c in this) {
        if (c == ' ') {
            lastIsSpace = true
        } else if (lastIsSpace) {
            lastIsSpace = false
            if (c in 'a'..'z') {
                resultBuilder.append(c - ('a' - 'A'))
            } else {
                resultBuilder.append(c)
            }
        } else {
            resultBuilder.append(c)
        }
    }
    return resultBuilder.toString()
}

fun fooExtend() {
    println("Convert this to camelcase".spaceToCamelCase())
}

//创建单例
object Resource {
    const val name = "Resource"
}

fun fooSingleton() {
    Resource.name
}

//If not null 缩写
//If not null and else 缩写
fun ifNotNull() {
    val files = File("test").listFiles()
    println(files?.size)
    println(files?.size ?: "empty")
}

//if null 执行一个语句
fun ifNull() {
    val values = mapOf("age" to 1, "name" to "David")
    val email = values["email"] ?: throw IllegalStateException("Email is missing!")


}

//在可能会空的集合中取第一元素
fun firstOrNull() {
    var emails = MutableList(1) { "" }
    val mainEmail = emails.firstOrNull() ?: ""
}

//if not null 执行代码
fun fooIfNotNull() {
    val value = null
    value?.let {
        // 代码会执行到此处, 假如data不为null
    }
}

//映射可空值（如果非空的话）
fun fooReflectNullable() {
    val value: Int? = null
    val mapped = value?.let { it + 1 } ?: 1
}

//返回 when 表达式
fun transform(color: String): Int {
    return when (color) {
        "Red" -> 1
        "Yellow" -> 2
        "Green" -> 3
        else -> throw IllegalArgumentException("invalid color")
    }
}

//“try/catch”表达式
fun fooTryCatch() {
    val result: Int = try {
        666
    } catch (e: ArithmeticException) {
        throw IllegalStateException(e)
    }

    // 使用 result
}

//“if”表达式
fun fooIF(param: Int) {
    val result = if (param == 1) {
        "One"
    } else if (param == 2) {
        "Two"
    } else {
        "Three"
    }
}

//返回类型为 Unit 的方法的 Builder 风格用法
fun arrayOfMinusOnes(size: Int): IntArray {
    return IntArray(size).apply { fill(-1) }
}

//单表达式函数
fun theAnswer() = 42

//等价于
fun theAnswer1(): Int {
    return 42
}

//单表达式函数与其它惯用法一起使用能简化代码，例如和 when 表达式一起使用：
fun transform1(color: String) = when (color) {
    "Red" -> 0
    "Green" -> 1
    "Blue" -> 2
    else -> throw IllegalArgumentException("Invalid color param value")
}

//对一个对象实例调用多个方法 （with）
class Turtle {
    fun penDown() {}
    fun penUp() {}
    fun turn(degrees: Double) {}
    fun forward(pixels: Double) {}
}

fun invokeMultiMethod() {
    val myTurtle = Turtle()
    with(myTurtle) { // 画一个 100 像素的正方形
        penDown()
        for (i in 1..4) {
            forward(100.0)
            turn(90.0)
        }
        penUp()
    }
}

//配置对象的属性（apply）
class Rectangle {
    var length: Int = 0
    var breadth: Int = 0
    var color: Int = 0
}

//这对于配置未出现在对象构造函数中的属性非常有用。
val myRectangle = Rectangle().apply {
    length = 4
    breadth = 5
    color = 0xFAFAFA
}

//Java 7 的 try with resources
fun tryWithResources() {
    val stream = Files.newInputStream(Paths.get("/some/file.txt"))
    stream.buffered().reader().use { reader ->
        println(reader.readText())
    }
}

//对于需要泛型信息的泛型函数的适宜形式
//  public final class Gson {
//     ……
//     public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
//     ……
inline fun <reified T : Any> Gson.fromJson(json: JsonElement): T =
    this.fromJson(json, T::class.java)

//使用可空布尔
fun nullBool() {
    val b: Boolean? = null
    if (b == true) {
        //
    } else {
        //false or null
    }
}

//交换两个变量
fun fooAlso() {
    var a = 1
    var b = 2
    a = b.also { b = a }
}

//TODO()：将代码标记为不完整
fun calcTaxes(): BigDecimal = TODO("Waiting for feedback from accounting")

class FooTodo {
    val toFill: Int = TODO("fix this value")
}